package com.ylr.send.framework.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ylr.send.common.dto.SmsLogDetailDto;
import com.ylr.send.common.dto.SmsLogDto;
import com.ylr.send.common.dto.SmsTemplateFlowDto;
import com.ylr.send.common.vo.SmsLogFormVo;
import com.ylr.send.framework.service.SmsLogService;
import com.ylr.send.framework.service.SmsTemplateFlowService;
import com.ylr.base.common.dto.PageDto;
import com.ylr.base.common.enums.ChannelEnum;
import com.ylr.base.common.enums.CommonEnum;
import com.ylr.base.common.enums.ModuleEnum;
import com.ylr.base.common.exception.YlrException;
import com.ylr.base.common.tool.PageQuery;
import com.ylr.base.framework.service.SnowflakeService;
import com.ylr.basic.framework.resolver.YbAesResolver;
import com.ylr.send.common.enums.SendResultEnum;
import com.ylr.send.common.enums.SmsChannelEnum;
import com.ylr.send.framework.entity.SmsLogEntity;
import com.ylr.send.framework.manager.SmsManager;
import com.ylr.send.framework.mapper.SmsLogMapper;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wyw
 * date: 2023-06-14 21:23:18
 * className: SmsLogServiceImpl
 * version: 1.0
 * description:
 */
@Service("ysSmsLogService")
@AllArgsConstructor
public class SmsLogServiceImpl extends ServiceImpl<SmsLogMapper, SmsLogEntity> implements SmsLogService {

    private static final Logger log = LoggerFactory.getLogger(SmsLogServiceImpl.class);

    private final SmsTemplateFlowService smsTemplateFlowService;

    private final SmsManager smsManager;

    private final SnowflakeService snowflakeService;

    private final YbAesResolver ybAesResolver;

    @Override
    public void saveSmsLog(Long smsTemplateId, Integer smsTemplateVersion, String mobile, String subMobile, Integer channel,
                           Integer module, String param, String result, Integer status, String createUser, Long createUserId,
                           String remark) {

        SmsLogEntity smsLog = new SmsLogEntity();
        smsLog.setId(snowflakeService.getId())
                .setSmsTemplateId(smsTemplateId)
                .setSmsTemplateVersion(smsTemplateVersion)
                .setMobile(mobile)
                .setSubMobile(subMobile)
                .setChannel(channel)
                .setModule(module)
                .setParam(param)
                .setResult(result)
                .setStatus(status)
                .setCreateTime(new Date())
                .setCreateUser(createUser)
                .setCreateUserId(createUserId)
                .setRemark(remark);
        // 添加数据
        baseMapper.insert(smsLog);
        log.info("保存短信发送记录完成");
    }

    @Transactional
    @Override
    public void batchSaveSmsLog(Long smsTemplateId, Integer smsTemplateVersion, List<String[]> mobileList, Integer channel,
                                Integer module, String param, String result, Integer status, String createUser, Long createUserId,
                                String remark) {
        List<SmsLogEntity> smsLogList = new ArrayList<>();
        Date date = new Date();
        for (String[] mobiles : mobileList) {
            SmsLogEntity smsLog = new SmsLogEntity();
            smsLog.setId(snowflakeService.getId())
                    .setSmsTemplateId(smsTemplateId)
                    .setSmsTemplateVersion(smsTemplateVersion)
                    .setMobile(mobiles[0])
                    .setSubMobile(mobiles[1])
                    .setChannel(channel)
                    .setModule(module)
                    .setParam(param)
                    .setResult(result)
                    .setStatus(status)
                    .setCreateTime(date)
                    .setCreateUser(createUser)
                    .setCreateUserId(createUserId)
                    .setRemark(remark);
            // 记录
            smsLogList.add(smsLog);
        }
        // 批量保存
        boolean bool = this.saveBatch(smsLogList);
        log.info("批量保存短信发送记录完成。bool={}", bool);
    }

    @Override
    public PageDto<SmsLogDto> pageSmsLogList(SmsLogFormVo smsLogFormVo) {
        // mp分页对象
        Page<SmsLogEntity> page = PageQuery.initPage(smsLogFormVo);

        String equalsMobile = null;
        String mobilePrefix = null;
        if (StringUtils.isNotBlank(smsLogFormVo.getMobile())) {
            if (SmsLogFormVo.MatchMode.EQUALS.getValue().equals(smsLogFormVo.getMobileMatchMode())) {
                equalsMobile = ybAesResolver.encryptToHex(smsLogFormVo.getMobile());
            }
            if (SmsLogFormVo.MatchMode.PREFIX.getValue().equals(smsLogFormVo.getMobileMatchMode())) {
                mobilePrefix = smsLogFormVo.getMobile();
            }
            if (StringUtils.length(mobilePrefix) > 3) {
                log.error("根据手机号前缀查询，手机号前缀长度大于3");
                throw new YlrException(SendResultEnum.MOBILE_PREFIX_LENGTH_FAIL);
            }
        }

        LambdaQueryWrapper<SmsLogEntity> smsLogLambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 查询字段
        smsLogLambdaQueryWrapper.select(SmsLogEntity::getId, SmsLogEntity::getSmsTemplateId, SmsLogEntity::getSmsTemplateVersion,
                SmsLogEntity::getSubMobile, SmsLogEntity::getChannel, SmsLogEntity::getModule, SmsLogEntity::getStatus,
                SmsLogEntity::getCreateTime, SmsLogEntity::getCreateUser, SmsLogEntity::getRemark);
        // 匹配条件
        smsLogLambdaQueryWrapper.eq(Objects.nonNull(smsLogFormVo.getSmsTemplateId()),
                        SmsLogEntity::getSmsTemplateId, smsLogFormVo.getSmsTemplateId())
                .eq(Objects.nonNull(smsLogFormVo.getSmsTemplateVersion()), SmsLogEntity::getSmsTemplateVersion,
                        smsLogFormVo.getSmsTemplateVersion())
                .eq(Objects.nonNull(equalsMobile), SmsLogEntity::getMobile, equalsMobile)
                .likeRight(Objects.nonNull(mobilePrefix), SmsLogEntity::getSubMobile, mobilePrefix)
                .eq(Objects.nonNull(smsLogFormVo.getChannel()), SmsLogEntity::getChannel, smsLogFormVo.getChannel())
                .eq(Objects.nonNull(smsLogFormVo.getModule()), SmsLogEntity::getModule, smsLogFormVo.getModule())
                .eq(Objects.nonNull(smsLogFormVo.getStatus()), SmsLogEntity::getStatus, smsLogFormVo.getStatus())
                .ge(Objects.nonNull(smsLogFormVo.getStartCreateTime()), SmsLogEntity::getCreateTime, smsLogFormVo.getStartCreateTime())
                .le(Objects.nonNull(smsLogFormVo.getEndCreateTime()), SmsLogEntity::getCreateTime, smsLogFormVo.getEndCreateTime())
                .eq(Objects.nonNull(smsLogFormVo.getCreateUserId()), SmsLogEntity::getCreateUserId, smsLogFormVo.getCreateUserId());
        // 查询数据
        baseMapper.selectPage(page, smsLogLambdaQueryWrapper);

        List<SmsLogEntity> smsLogList = page.getRecords();
        long totalNum = page.getTotal();
        if (smsLogList.isEmpty()) {
            log.info("短信发送记录为空");
            return new PageDto<>(Collections.emptyList(), totalNum, smsLogFormVo.getPageNo(), smsLogFormVo.getPageSize());
        }
        // 数据封装
        List<SmsLogDto> smsLogDtoList = smsLogList.stream().map(this::getSmsLogDto).collect(Collectors.toList());
        return new PageDto<>(smsLogDtoList, totalNum, smsLogFormVo.getPageNo(), smsLogFormVo.getPageSize());
    }

    @Override
    public SmsLogDto getSmsLog(Long id) {
        // 获取短信发送记录
        SmsLogEntity smsLog = this.findSmsLog(id);
        return this.getSmsLogDto(smsLog);
    }

    @Override
    public SmsLogDetailDto getSmsLogDetail(Long id) {

        // 1、获取短信发送记录
        SmsLogEntity smsLog = this.findSmsLog(id);

        Map<String, String> paramMap = new HashMap<>();
        if (StringUtils.isNotBlank(smsLog.getParam())) {
            // 解密
            String param = ybAesResolver.decodeHex(smsLog.getParam());
            // 反序列化
            paramMap = JSON.parseObject(param, new TypeReference<>() {});
        }
        Map<String, String> resultMap = Collections.emptyMap();
        if (StringUtils.isNotBlank(smsLog.getRemark())) {
            // 解密
            String result = ybAesResolver.decodeHex(smsLog.getParam());
            // 反序列化
            resultMap = JSON.parseObject(result, new TypeReference<>() {});
        }

        // 2、获取短信模板流水
        SmsTemplateFlowDto smsTemplateFlow = smsTemplateFlowService.getSmsTemplateFlow(smsLog.getSmsTemplateId(),
                smsLog.getSmsTemplateVersion());

        // 3、生成短信发送内容
        String smsContent = smsManager.buildContent(smsTemplateFlow.getChannel(), smsTemplateFlow.getContent(),
                paramMap, true);

        // 4、数据封装
        SmsLogDetailDto smsLogDetailDto = new SmsLogDetailDto();
        smsLogDetailDto.setMobile(ybAesResolver.decodeHex(smsLog.getMobile()))
                .setRequestChannel(smsLog.getChannel())
                .setRequestChannelName(
                        Optional.ofNullable(ChannelEnum.getChannelEnum(smsLog.getChannel()))
                            .map(ChannelEnum::getName)
                            .orElse(StringUtils.EMPTY)
                )
                .setRequestModule(smsLog.getModule())
                .setRequestModuleName(
                        Optional.ofNullable(ModuleEnum.getModuleEnum(smsLog.getModule()))
                                .map(ModuleEnum::getName)
                                .orElse(StringUtils.EMPTY)
                )
                .setParamMap(paramMap)
                .setResultMap(resultMap)
                .setStatus(smsLog.getStatus())
                .setStatusName(
                        Optional.ofNullable(CommonEnum.getStatusEnum(smsLog.getStatus()))
                                .map(CommonEnum::getName)
                                .orElse(StringUtils.EMPTY)
                )
                .setCreateTime(smsLog.getCreateTime())
                .setCreateUser(smsLog.getCreateUser())
                .setRemark(smsLog.getRemark())
                .setSmsChannel(smsTemplateFlow.getChannel())
                .setSmsChannelName(
                        Optional.ofNullable(SmsChannelEnum.getChannelEnum(smsTemplateFlow.getChannel()))
                                .map(SmsChannelEnum::getName)
                                .orElse(StringUtils.EMPTY)
                )
                .setTemplateName(smsTemplateFlow.getTname())
                .setContent(smsTemplateFlow.getContent())
                .setSmsContent(smsContent)
                .setVersion(smsTemplateFlow.getVersion());
        return smsLogDetailDto;
    }

    /**
     * 获取短信发送记录
     * @param id 主键
     * @return 短信发送记录对象
     */
    private SmsLogEntity findSmsLog(Long id) {
        SmsLogEntity smsLog = baseMapper.selectById(id);
        if (Objects.isNull(smsLog)) {
            log.error("短信发送记录不存在");
        }
        return smsLog;
    }

    /**
     * 短信发送记录数据封装
     * @param smsLog 参数对象
     * @return 封装结构
     */
    private SmsLogDto getSmsLogDto(SmsLogEntity smsLog) {
        SmsLogDto smsLogDto = new SmsLogDto();
        smsLogDto.setId(smsLog.getId().toString())
                .setSmsTemplateId(smsLog.getSmsTemplateId().toString())
                .setSmsTemplateVersion(smsLog.getSmsTemplateVersion())
                .setMobile(smsLog.getMobile())
                .setSubMobile(smsLog.getSubMobile())
                .setChannel(smsLog.getChannel())
                .setModule(smsLog.getModule())
                .setStatus(smsLog.getStatus())
                .setCreateTime(smsLog.getCreateTime())
                .setCreateUser(smsLog.getCreateUser())
                .setRemark(smsLog.getRemark());
        if (StringUtils.isNotBlank(smsLog.getParam())) {
            String param = ybAesResolver.decodeHex(smsLog.getParam());
            Map<String, String> paramMap = JSON.parseObject(param, new TypeReference<>() {});
            smsLogDto.setParamMap(paramMap);
        }
        if (StringUtils.isNotBlank(smsLog.getResult())) {
            String result = ybAesResolver.decodeHex(smsLog.getResult());
            Map<String, String> resultMap = JSON.parseObject(result, new TypeReference<>() {});
            smsLogDto.setResultMap(resultMap);
        }
        return smsLogDto;
    }



}